from qturboframe.lib.utils.by import By
from qturboframe.lib.utils.assertion import Assertion
from qturboframe.lib.ranorex.exceptions import CsClientError
from qturboframe.lib.ranorex.win_control.control import Control
from qturboframe.lib.utils.TimeMeta import TimeMeta
from qturboframe.lib.utils.CustomError.custom_error import CustomError

class BaseControl(TimeMeta):
    """
    WPF组件基础控件类

    :Attributes:
     - _driver: 控件所在的当前Control对象
     - _control: 控件元素Control对象
     - timeout: 步骤操作的超时时间

    :Example:
     - 例1: BaseControl(control)
     - 例2: BaseControl({By.RANOREXPATH:'ranorexpath'})
     - 例4: BaseControl({By.XPATH:'xpath','text':'文本信息'})
     - 例5: BaseControl({By.AUTOMATIONID:'automationid','text':'文本信息'}, father=driver)
    """
    def __init__(self, element_para, father=None, timeout=10000):
        self.timeout = timeout

        if isinstance(element_para, Control):
            self._control = element_para
            self._driver = Control(element_para.control)
            self.xpath = self._control.get_path()
        elif hasattr(element_para,"_control") and isinstance(element_para._control, Control):
            self._control = element_para._control
            self._driver = Control(element_para._control.control)
            self.xpath = self._control.get_path()
        elif not isinstance(element_para, dict):
            message = 'element_para参数类型不正确！'
            raise CsClientError(CustomError.Error_EQ03008001_Parameter_InCorrect, message)
        else:
            if father is None:
                message = '未定位元素，father参数不能为None！'
                raise CsClientError(CustomError.Error_EQ03008001_Parameter_InCorrect, message)
            if isinstance(father, Control):
                self._driver = father
                self.timeout = timeout
            else:
                message = 'father参数类型不正确！'
                raise CsClientError(CustomError.Error_EQ03008001_Parameter_InCorrect, message)

            element_by = None
            element_value = None
            assist = ''
            if isinstance(element_para, dict) and By.AUTOMATIONID in element_para:
                element_by = By.XPATH
                element_value = ".//*[@automationid='{}']".format(element_para.get(By.AUTOMATIONID))
            else:
                key_list = [By.XPATH, By.RANOREXPATH]
                for key, value in element_para.items():
                    if key.lower() in key_list:
                        element_by = key
                        element_value = value
                    else:
                        assist += '{}:{},'.format(key, value)
                assist = assist.strip(',')

            self._control = father.find_element_by_attribute(
                element_by, element_value, assist, self.timeout)
            self.xpath = element_value

            # self.controls = father.find_elements_by_attribute(
            #     element_by, element_value, assist, self.timeout)
            # self.xpath = element_value
            # for control in self.controls:
            #     if control.is_visible():
            #         self._control = control
            #         break
            # else:
            #     raise CsClientError("按照此路径{}没有找到可见的控件".format(str(element_para)))

    def get_text_of_textblock(self, element_ctrl):
        """
        获取控件中Type为TextBlock中text控件上的文本信息

        :Args:
         - element_ctrl: 需要获取文本信息的控件

        :Raise:
         - None

        :Example:
         - 例1: base_control.get_text_of_textblock(container)
        """
        xpath = ".//text[@Type='TextBlock']"
        element = element_ctrl.exist("xpath", xpath, timeout=0.5)
        if element:
            return element.get_text()
        else:
            return ""

    def get_visible_element(self, controls):
        """
        返回输入控件中可见的控件

        :Args:
         - controls: 输入的控件

        :Raise:
         - None

        :Example:
         - 例1: base_control.get_visible_element(containers)
        """
        visible_elements = []
        for control in controls:
            if control.is_visible():
                visible_elements.append(control)
            else:
                control.ensure_visible()
                if control.is_visible():
                    visible_elements.append(control)
        return visible_elements

    def check(self, expected_value, actual_value):
        '''
        检查期望值和实际值是否相等

        :Args:
         - expected_value: 期望值
         - actual_value: 实际值

        :Returns:
            操作失败返回false，成功返回true

        :Raises:
            CsClientError: 期望值和实际值不符

        :Example:
         - 例: base_control.check(expected_value,actual_value)
        '''
        try:
            Assertion(expected_value).check_string(actual_value.strip())
        except:
            raise CsClientError(CustomError.Error_EQ03010001_Verify_Expect_Actual_Not_Equal,'界面取值为“{}”，期望值为“{}”，期望值和实际值不符！'.format(
                actual_value, expected_value))
